#!/usr/bin/env python

import config
import socket
import string
import threading
import time
import wx

import strings as s
import irc

#---Protocol Stuff

class ConnectionReceiver(threading.Thread):
    def __init__(self, connection):
        threading.Thread.__init__(self)
        self.connection = connection
        self.running = True
        self.start()
        
    def stop(self):
        self.running = False
        
    def run(self):
        readbuffer = ""
        while self.running:
            readbuffer = readbuffer + self.connection.socket.recv(1024)
            temp = string.split(readbuffer, "\n")
            readbuffer = temp.pop( )
        
            for line in temp:
                line = string.rstrip(line)
                if self.running:
                    self.connection.processMessage(line)
    

class ConnectionTransmitter(threading.Thread):
    def __init__(self, connection):
        threading.Thread.__init__(self)
        self.connection = connection
        self.buffer = []
        self.running = True
        self.start()

    def stop(self):
        self.running = False
        
    def send(self, line):
        self.buffer.append(line)
        
    def run(self):
        while self.running:
            if (len(self.buffer) > 0):
                line = self.buffer.pop(0)
                print ">>> %s" % line
                self.connection.socket.send(line + "\r\n")
            else:
                time.sleep(0.1)
                

class Connection(object):
    def __init__(self, callback, server, port, nick, 
                 ident="foo", name="foo"):
        self.server = server
        self.port = port
        self.nick = nick
        self.ident = ident
        self.name = name
        self.callback = callback

        self.socket = socket.socket( )
        self.socket.connect((self.server, self.port))

        self.receiver = ConnectionReceiver(self)
        self.transmitter = ConnectionTransmitter(self)

        self.transmitter.send("NICK %s" % self.nick)
        self.transmitter.send("USER %s %s bla :%s" 
                         % (self.ident, self.server, self.name))
        
                    
    def processMessage(self, line):
        msg = Message(self, line)
            
        # ping-pong
        if(msg.words[0]=="PING"):
            self.transmitter.send("PONG %s" % msg.words[1])
            return True
        
        wx.CallAfter(self.callback, msg)
        
    def close(self):
        self.receiver.stop()
        self.transmitter.stop()
        self.socket.close()    
        
    def join(self, channel):
        self.transmitter.send("JOIN %s" % channel)
        
class Message():
    def __init__(self, connection, line):
        self.connection = connection
        self.line = line
        self.removeColourCodes()
        self.decodeCharset()
        
        self.words = string.split(self.line)
        self.sender = ""
        self.nick = ""
        self.command = ""
        self.room = ""
        self.text = ""
        self.list = []
            
        try:
            self.sender = self.words[0][1:]
            self.command = self.words[1]
            self.nick = self.sender.split("!")[0]
            
            if self.words[0] == "PING":
                self.command = "ping"
                self.nick = ""
                self.text = self.words[1]
        
            if (self.command in ["PRIVMSG", "NOTICE"]):
                if (self.words[2][0] == "#"):
                    self.command = "chat"
                    self.room = self.words[2].lower()
                    self.text = " ".join(self.words[3:])[1:]
                else:
                    self.command = "im"
                    self.text = " ".join(self.words[3:])[1:]
 
            if self.command == "JOIN":
                self.command = "join"
                self.room = self.words[2][1:].lower()
            
            if self.command == "PART":
                self.command = "part"
                self.room = self.words[2].lower()
                self.text = " ".join(self.words[3:])[1:]
                
            if self.command == "QUIT":
                self.command = "quit"
                self.text = " ".join(self.words[2:])[1:]
                
            # names reply    
            if (self.command == "353"):
                self.command = "room_members"
                self.room = self.words[4].lower()
                self.list = self.words[5:]
                self.list[0] = self.list[0][1:] 
            
            # MOTD
            if (self.command in ["375", "372", "376"]):
                self.command = "im"
                self.text = " ".join(self.words[3:])[1:]
                
            #whois
            if (self.command in ["401", "311", "319", "312", "317", "318"]):
                self.command = "im"
                self.text = " ".join(self.words[3:])
            

            # 0xx, 1xx, 2xx
            if (self.command[0] in ["0", "1", "2"]):
                self.command = "im"
                self.text = " ".join(self.words[3:])
                    
        except IndexError:
            pass
        
        if self.command not in ["chat", "join", "part", "quit"]:
            self.debugOut()
        
    def removeColourCodes(self):
        tmp = ""
        cc = False
        for char in self.line:
            if ord(char) == 3:
                cc = True
            if not char in "0123456789," + chr(3):
                # this mIRC color coding protocol is so sick!
                # I wonder what one has to smoke to come up with 
                # something unparsable like this for such a
                # simple task. </rant>
                cc = False 
            if not cc:
                if ord(char) > 0x1f: 
                    # also remove all other characters below 0x20
                    tmp += char
        self.line = tmp
                
    def decodeCharset(self):
        self.line = self.line.decode(config.default_encoding)
        
    def debugOut(self):
        print "       " + self.line.encode("utf-8")
        print " nick: " + self.nick.encode("utf-8")
        print "  cmd: " + self.command.encode("utf-8")
        print " room: " + self.room.encode("utf-8")
        print " text: " + self.text.encode("utf-8")
        print " list: " + str(self.list).encode("utf-8")
        print "----------------------------------------------------------"
        
    